﻿/******************************************************
* author :  cwj
* email  :  chenwenji_360@live.com 
* history:  created by cwj 2015/8/19 13:40:10 
* clrversion :4.0.30319.42000
******************************************************/

using Machine.DataAccess.Linq.Relation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Machine.DataAccess.Linq
{
    class MySqlFormat : SetFormatBase
    {
        public MySqlFormat(ProviderElement providerElement) : base(providerElement) { }

        //protected override Expression VisitTable(TableExpression table)
        //{
        //    //this.build.Append("[");
        //    this.build.Append(table.TableName);
        //    //this.build.Append("]");
        //    this.build.Append(" as ");
        //    this.build.Append(table.TableArg);
        //    return table;
        //}

        protected override Expression VisitSelect(SelectExpression select)
        {
            this.build.Append("Select ");
            //if (select.Top > 0)
            //{
            //    this.build.Append("Top(");
            //    this.build.Append(select.Top);
            //    this.build.Append(") ");
            //}
            for (int i = 0; i < select.Colums.Count(); i++)
            {
                reNameColum = true;
                if (i > 0) this.build.Append(",");
                var colum = select.Colums.ElementAt(i);
                var columExpression = this.Visit(colum.ColumExpression) as ColumExpression;
                if (columExpression == null || columExpression.Name != colum.ColumName)
                {
                    this.build.Append(" as ");
                    this.build.Append(columExpression.Name);
                }
                reNameColum = false;
            }
            if (select.Colums.Count() == 0)
            {
                this.build.Append(" Count(*) ");
            }
            if (select.From != null || select.JoinSingleType.Count() > 0)
            {
                //this.build.Append(" From ");
                //this.VisitSource(select.From);
                //if (select.JoinSingleType.Count() > 0)
                //{
                //}
                this.build.Append(" From ");
                var tableExpression = select.From as TableExpression;
                this.VisitSource(tableExpression);
                if (select.JoinSingleType.Count() > 0)
                {
                    VistJoinSingleType(select, tableExpression);
                }
            }
            if (select.Where != null || select.Skip > 0)
            {
                this.build.Append(" Where ");
                this.Visit(select.Where);
                if (select.Skip > 0) this.VisitSkip(select);
            }
            if (select.OrderBy != null && select.OrderBy.Count() > 0 && select.Colums.Count() > 0)
            {
                this.build.Append(" Order By ");

                for (int i = 0; i < select.OrderBy.Count(); i++)
                {
                    if (i > 0) this.build.Append(",");
                    var item = select.OrderBy.ElementAt(i).ColumExpression as ColumExpression;
                    this.build.Append(item.TableArg);
                    this.build.Append(".");
                    this.build.Append(item.Name);
                }
                this.build.Append(" ");
                this.build.Append(select.OrderByType);
            }

            if (select.Top > 0)
            {
                this.build.Append(" Limit ");
                this.build.Append(select.Top);
            }
            return select;
        }

        protected override Expression VisitGeoDistance(GeoDistanceExpression geo)
        {
            var schem = Config.Instance.GetDbSchemInfo(this.ProviderElement).GetSchem(geo.TableType);
            var primaryKeyName = schem.PrimaryKeyName;
            string geoString = " left join (select {0},2 * 6370996.81 * ASIN(SQRT(POW(PI() *({1} - {2}) / 360, 2) + COS(PI() * {1} / 180) * COS(PI() * {2} / 180) * POW(SIN(PI() *({3} - {4}) / 360),2))) as '{5}' FROM {6}) AS t{7} ON t{8}.Id = t{7}.Id  ";

            geoString = string.Format(geoString, primaryKeyName, geo.LatName, geo.Lat, geo.LngName, geo.Lng, geo.DistanceName, geo.TableType.Name, geo.TableIndex, geo.OldTableIndex);

            this.build.Append(geoString);

            return base.VisitGeoDistance(geo);
        }
    }
}
